
// ===============================================================================================================
// -*- C++ -*-
//
// Texture.hpp - Definition of a texture interface and an OpenGL texture classe.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#ifndef __TEXTURE_HPP__
#define __TEXTURE_HPP__

// C++ std includes
#include <memory>
#include <string>

// Local includes
#include <Image.hpp>
#include <RefPtr.hpp>
#include <ReferenceCountable.hpp>

// ===============================================================================================================
// Texture class diagram:
//
//     +--------- (abs)         +-------------------- (abs)
//     |  Texture  | ---------> |  ReferenceCountable  |
//     +-----------+            +----------------------+
//           ^
//           |
//   +-----------------+
//   |  GL_2D_Texture  | ---------------> By using a virtual interface for the textures one can
//   +-----------------+                  change the real texture implemtation easily to support other APIs.
//
// ===============================================================================================================

///
/// Texture -- Texture base class.
/// This is an abstract base class for more specialized OpenGL texture classes.
/// Texture objects can only be created by the Renderer class.
///
/// The Texture class is reference counted.
///
class Texture : public ReferenceCountable {

public:

	// Constants:

	enum {

		DEFAULT  = (1 << 0), ///< Default behaviour
		COMPRESS = (1 << 1), ///< Use texture compression
	};

	typedef int TextureFlags;

public:

	// Public Interface:

	Texture(void);

	/// Checks if the texture creation failed.
	bool Fail(void) const;

	/// True if using the OpenGL standard coord system.
	bool StdCoordSystem(void) const;

	/// Get the name of the image file that originated the texture.
	const std::string & FileName(void) const;

	/// Binds a texture to a geometry.
	virtual void Bind(unsigned int texUnit = 0) const = 0;

	// ReferenceCountable Methods:

	virtual unsigned long AddRef(void) const;
	virtual unsigned long Release(void) const;
	virtual unsigned long ReferenceCount(void) const;

protected:

	virtual ~Texture(void) { /* Not allowed to be directly deleted */ }

	// Member Variables:

	TextureFlags flags;   ///< Texture compression flags
	std::string fileName; ///< File that originated the texture

	bool standardCoordSystem; ///< GL std coord system
	bool failBit; ///< Set if an error ocurred during creation
};

///
/// Reference countable texture pointer type.
///
typedef RefPtr<Texture> TexturePtr;

// ===============================================================================================================

///
/// GL_2D_Texture -- OpenGL 2D texture object.
///
class GL_2D_Texture : public Texture {

public:

	// Public Interface:

	/// Construct from image object.
	GL_2D_Texture(const Image * img, TextureFlags imgFlags = Texture::DEFAULT);

	/// Binds a texture to a geometry.
	virtual void Bind(unsigned int texUnit = 0) const;

protected:

	virtual ~GL_2D_Texture(void);

	GL_2D_Texture(void) { /* Default constructor is not public */ };

	/// Create a texture 2D from an image.
	virtual bool Create(const Image * img, TextureFlags imgFlags);

	/// Return the corresponding format for a compressed image given image's internal format (pixel components).
	virtual GLint GetCompressionFormat(GLint components) const;

private:

	GLuint id; ///< The OpenGL texture id
};

#endif // __TEXTURE_HPP__